package ru.braim.weather_app.services;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import ru.braim.weather_app.dto.weather.WeatherRequestDTO;
import ru.braim.weather_app.dto.weather.WeatherResponseDTO;
import ru.braim.weather_app.models.Region;
import ru.braim.weather_app.models.Weather;
import ru.braim.weather_app.models.WeatherForecast;
import ru.braim.weather_app.models.enums.WeatherCondition;
import ru.braim.weather_app.repositories.RegionRepository;
import ru.braim.weather_app.repositories.WeatherForecastRepository;
import ru.braim.weather_app.repositories.WeatherRepository;
import ru.braim.weather_app.responses.weather.WeatherResponse;

import java.util.ArrayList;
import java.util.List;

@Service
public class WeatherService {

    private final WeatherRepository weatherRepository;
    private final RegionRepository regionRepository;
    private final WeatherForecastRepository weatherForecastRepository;


    public WeatherService(WeatherRepository weatherRepository, RegionRepository regionRepository,
                          WeatherForecastRepository weatherForecastRepository) {
        this.weatherRepository = weatherRepository;
        this.regionRepository = regionRepository;
        this.weatherForecastRepository = weatherForecastRepository;
    }


    public WeatherResponse createWeather(WeatherRequestDTO weatherRequestDTO) {

        if (!weatherRequestDTO.isValidWeatherRequest()) {
            return new WeatherResponse(null, HttpStatus.BAD_REQUEST);
        }

        Region region = regionRepository.getRegionById(weatherRequestDTO.getRegionId());

        if (region == null) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        if (weatherRequestDTO.getWeatherForecast() == null) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }


        if (weatherRequestDTO.getWeatherForecast().isEmpty()) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        List<WeatherForecast> weatherForecastList = new ArrayList<>();
        for (Long forecastId : weatherRequestDTO.getWeatherForecast()) {

            if (forecastId == null) {
                return new WeatherResponse(null, HttpStatus.NOT_FOUND);
            }

            WeatherForecast weatherForecast = weatherForecastRepository.getWeatherForecastById(forecastId);

            if (weatherForecast == null) {
                return new WeatherResponse(null, HttpStatus.NOT_FOUND);
            }

            weatherForecastList.add(weatherForecast);

        }

        Weather weather = new Weather();

        weather.setRegion(region);
        weather.setTemperature(weatherRequestDTO.getTemperature());
        weather.setHumidity(weatherRequestDTO.getHumidity());
        weather.setWindSpeed(weatherRequestDTO.getWindSpeed());
        weather.setWeatherCondition(WeatherCondition.getWeatherCondition(weatherRequestDTO.getWeatherCondition()));
        weather.setPrecipitationAmount(weatherRequestDTO.getPrecipitationAmount());
        weather.setMeasurementDateTime(weatherRequestDTO.getMeasurementDateTime());
        weather.setWeatherForecast(weatherForecastList);

        weatherRepository.save(weather);

        WeatherResponseDTO weatherResponseDTO = new WeatherResponseDTO();

        weatherResponseDTO.setId(weather.getId());
        weatherResponseDTO.setTemperature(weather.getTemperature());
        weatherResponseDTO.setHumidity(weather.getHumidity());
        weatherResponseDTO.setWindSpeed(weather.getWindSpeed());
        weatherResponseDTO.setWeatherCondition(weather.getWeatherCondition().getWeatherCondition());
        weatherResponseDTO.setPrecipitationAmount(weather.getPrecipitationAmount());
        weatherResponseDTO.setMeasurementDateTime(weather.getMeasurementDateTime());

        List<Long> weatherForecastIds = new ArrayList<>();

        for (WeatherForecast forecast : weatherForecastList) {
            weatherForecastIds.add(forecast.getId());
        }

        weatherResponseDTO.setWeatherForecast(weatherForecastIds);
        weatherResponseDTO.setRegionName(region.getName());

        return new WeatherResponse(weatherResponseDTO, HttpStatus.OK);


    }

    public WeatherResponse getWeatherByRegionId(Long regionId) {

        if (regionId <= 0) {
            return new WeatherResponse(null, HttpStatus.BAD_REQUEST);
        }

        Region region = regionRepository.getRegionById(regionId);

        if (region == null) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        if (region.getWeathers() == null) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        if (region.getWeathers().isEmpty()) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        Weather weather = region.getWeathers().get(region.getWeathers().size() - 1);

        if (weather == null) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        if (weather.getWeatherForecast() == null) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        if (weather.getWeatherForecast().isEmpty()) {
            return new WeatherResponse(null, HttpStatus.NOT_FOUND);
        }

        List<Long> weatherForecastIds = new ArrayList<>();
        for (WeatherForecast forecast : weather.getWeatherForecast()) {
            weatherForecastIds.add(forecast.getId());
        }

        WeatherResponseDTO weatherResponseDTO = new WeatherResponseDTO();

        weatherResponseDTO.setId(region.getId());
        weatherResponseDTO.setRegionName(region.getName());

        weatherResponseDTO.setTemperature(weather.getTemperature());
        weatherResponseDTO.setHumidity(weather.getHumidity());
        weatherResponseDTO.setWindSpeed(weather.getWindSpeed());
        weatherResponseDTO.setWeatherCondition(weather.getWeatherCondition().getWeatherCondition());
        weatherResponseDTO.setPrecipitationAmount(weather.getPrecipitationAmount());
        weatherResponseDTO.setMeasurementDateTime(weather.getMeasurementDateTime());
        weatherResponseDTO.setWeatherForecast(weatherForecastIds);



        return new WeatherResponse(weatherResponseDTO, HttpStatus.OK);

    }

}
